package cn.e2win.base.service;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

import cn.e2win.base.dao.GenericDAO;
import cn.e2win.base.entity.BaseEntity;
import cn.e2win.base.entity.SysUser;
import cn.e2win.biz.util.GenericsUtils;


public abstract class BaseMvcService<T extends BaseEntity, PK extends Serializable> implements BaseMvcServiceIf<T, PK>, InitializingBean{
	private GenericDAO<T, PK> dao;
	
	public abstract GenericDAO <T, PK> initDao();

	/*@Autowired
	private NativeMapQuery nativeDao;*/
	
	
	@Override
	public void afterPropertiesSet() throws Exception {
		this.dao = this.initDao();
	}
	
	@Override
	public List<T> getAll() {
		return dao.readAll();
	}

	@Transactional
	public void delete(PK id){
		//dao.delete(id);
		T t = dao.read(id);
		t.setActiveStatusInt(0);
		dao.store(t);
	}
	
	@Transactional
	public void delete(PK[] ids){
		//dao.delete(ids);
		for(PK id : ids){
			T t = dao.read(id);
			t.setActiveStatusInt(0);
			dao.store(t);
		}
	}
	
	@Transactional
	public void physicDelete(PK id){
		dao.delete(id);
	}
	
	@Transactional
	public void physicDelete(PK[] ids){
		dao.delete(ids);
	}
	
	
	@Transactional
	public T get(PK id){
		return dao.read(id);
	}
	

	@Transactional
	public void add(T t){
		dao.store(t);
	}
	
	@Transactional
	public void update(T t, SysUser user) {
		/**
		 * 
		 * 这里需要用反射来判断
		 * 先从DB读取一个,找到ID,再读一个
		 * 再判断页面传过偶来的字段是否为空,为空就不更新
		 * 为空字符串的字段需要更新(比如需要清空一个属性的时候)
		 */
		try {
				PK id = (PK)GenericsUtils.getPKValue(t);
				if(id!=null){
					T objOld = dao.read(id);
					GenericsUtils.setFieldValue(t, objOld);
					setCurrentUserInfo(objOld, user);
					dao.update(objOld);
				}else {
					setCurrentUserInfo(t, user);
					dao.store(t);
				}
			
		} catch (Exception e) {
			//logger.error(e);
			throw new RuntimeException("update failed!",e);
		}
		
	}

	@Transactional
	public void save(T t, SysUser user){
		dao.store(t);
	}
	
	
	

	/**
	 * set add info and update info
	 * @param user
	 * @param object
	 */
	public void setCurrentUserInfo(Object object, SysUser user){
		
		String getIdMethod = "getId";
		
		try {
			Method getId = object.getClass().getDeclaredMethod(getIdMethod);
			Object id = getId.invoke(object);

			String setDateMethod = "setUpdateDate";
			String setUserMethod= "setUpdateById";
			if(id==null){
				setDateMethod = "setCreateDate";
				setUserMethod= "setCreateById";
				

				Method setCoid = object.getClass().getSuperclass().getDeclaredMethod("setCoId", Integer.class);
				setCoid.invoke(object, user.getCoId());
				
			}

			Method setActiveStatus = object.getClass().getSuperclass().getDeclaredMethod("setActiveStatusInt", Integer.class);
			setActiveStatus.invoke(object, 1);
			
			Method setDate = object.getClass().getSuperclass().getDeclaredMethod(setDateMethod, Timestamp.class);
			setDate.invoke(object, new Timestamp(new Date().getTime()));
			if (null == user) {
				return;
			}
			Method setUser = object.getClass().getSuperclass().getDeclaredMethod(setUserMethod, Integer.class);
			setUser.invoke(object, user.getId());
			
			
			
			
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e);
		}
	}

	 
	public Object getEntity(Class clazz, Serializable id){
		return dao.getEntity(clazz, id);
		
	}
}
